/*
 * 客户端提交的账户密码请求授权登录
 */
package labox.innovation.loginserver.socket.clientpackets;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;
import labox.innovation.loginserver.HackingException;
import labox.innovation.loginserver.socket.LoginClient;
import labox.innovation.loginserver.LoginController;
import labox.innovation.loginserver.GameServerTable.GameServerInfo;
import labox.innovation.loginserver.socket.LoginClient.LoginClientState;
import labox.innovation.loginserver.LoginController.AuthLoginResult;
import labox.innovation.loginserver.socket.serverpackets.ResouceUpdate;
import labox.innovation.loginserver.socket.serverpackets.ServerList;
import labox.innovation.loginserver.socket.serverpackets.LoginFail.LoginFailReason;
import labox.innovation.loginserver.svn.Svn.Data;
import labox.innovation.util.Rnd;

/**
 * Format: x 0 (a leading null) x: the rsa encrypted block with the login an password
 */
public class RequestAuthLogin extends LoginClientPacket {

	private static final Logger _log = LoggerFactory.getLogger(RequestAuthLogin.class.getName());

	/**
	 * 用户名
	 */
	private String _user;

	/**
	 * 密码
	 */
	private String _password;

	/**
	 * Sdk
	 */
	private byte _sdk;

	/**
	 * 渠道ID
	 */
	private String _channelID;

	/**
	 * 手机平台信息
	 */
	private String _clientInfo;

	/**
	 * 协议版本号
	 */
	private int _clientVersion;

	/**
	 * 资源版本号
	 */
	private int _resVersion;

	/**
	 * @return
	 */
	public String getPassword() {
		return _password;
	}

	/**
	 * @return
	 */
	public String getUser() {
		return _user;
	}

	/**
	 * 客户端端版本问题目前还需要讨论
	 * 
	 * @param clientVersion
	 * @return
	 */
	private boolean checkClientVersion(int clientVersion) {//临时解决方案
		return true;
	}

	@Override
	public void readImpl() {
		_user = readString();
		_password = readString();
		_sdk = readByte();
		_channelID = readString();
		_clientInfo = readString();
		_clientVersion = readInt();
		_resVersion = readInt();
	}

	@Override
	public void run() {
		LoginController lc = LoginController.getInstance();

		//进行必要的简单检查
		if (_user == null || !lc.isValidName(_user)) {
			getClient().close(LoginFailReason.REASON_ACCESS_FAILED.getLoginFail());
			return;
		}

		if (_password == null || !lc.isValidPassword(_password)) {
			getClient().close(LoginFailReason.REASON_ACCESS_FAILED.getLoginFail());
			return;
		}

		if (!checkClientVersion(_clientVersion)) { //-- 版本检查
			getClient().sendPacket(LoginFailReason.REASON_VERSION_ERROR.getLoginFail());
		} else {
			LoginClient client = getClient();

			try {

				AuthLoginResult result = lc.tryAuthLogin(_user, _password, client); //-- 对用户口令以及是否是屏蔽账户做鉴权

				switch (result) {
				case AUTH_SUCCESS: //-- 鉴权成功
					if (!checkRes(client))
						return;
					client.setAccount(_user);
					client.setChannelId(_channelID);
					client.setState(LoginClientState.AUTHED_LOGIN); //-- 设置登陆客户端当前进度状态
					client.setSessionKey(Rnd.nextInt());
					client.close(new ServerList(client));
					//-- 更新用户账户信息
					LoginController.getInstance().resetAccountInfo(_user, _password, this.getClient().getInetAddress().getHostAddress(), _sdk, _channelID, _clientInfo, _clientVersion);
					break;
				case INVALID_PASSWORD: //-- 密码错误
					client.close(LoginFailReason.REASON_USER_OR_PASS_WRONG.getLoginFail());
					break;
				case ACCOUNT_BANNED: //-- 账户被屏蔽
					client.close(LoginFailReason.REASON_PERMANENTLY_BANNED.getLoginFail());
					break;
				case ALREADY_ON_LS: //-- 如果已经在登录服务器上，不处理
					LoginClient oldClient;
					if ((oldClient = (LoginClient) lc.getAuthedClient(_user)) != null) {
						//踢掉之前登陆用户
						client.close(LoginFailReason.REASON_ACCOUNT_IN_USE.getLoginFail());
						lc.removeAuthedLoginClient(_user);
					}
					break;
				case ALREADY_ON_GS: //-- 已经在游戏服务器上玩家
					GameServerInfo gsi;
					if ((gsi = lc.getAccountOnGameServer(_user)) != null) {
						client.close(LoginFailReason.REASON_ACCOUNT_IN_USE.getLoginFail());
						//把这个账户已经在某个服务器上的角色踢下线
						if (gsi.isAuthed()) {
							gsi.getGameServerThread().kickPlayer(_user);
						}
					}
					break;
				}
			} catch (HackingException e) {
				InetAddress address = client.getConnection().getInetAddress();
				lc.addBanForAddress(address, Config.LOGIN_BLOCK_AFTER_BAN * 1000); //-- 绑定时间
				_log.info("Banned (" + address + ") for " + Config.LOGIN_BLOCK_AFTER_BAN + " seconds, due to " + e.getConnects() + " incorrect login attempts.", Config.SERVER_ID, e);
			}
		}
	}

	public boolean checkRes(LoginClient client) {
		LoginController lc = LoginController.getInstance();
		Map<Integer, ArrayList<Data>> updata = lc.getSVN().checkVer(_resVersion);
		if (updata == null)
			return true;
		for (Map.Entry<Integer, ArrayList<Data>> en : updata.entrySet()) {
			int type = en.getKey();
			ArrayList<Data> data = en.getValue();
			for (int i = -1; ++i < data.size();) {
				Data d = data.get(i);
				client.sendPacket(new ResouceUpdate(type, d.getInt(), d.getData()));
			}
		}
		client.sendPacket(new ResouceUpdate(ResouceUpdate.SVN_NEWVERSION, lc.getSVN().getVer(), null));

		return false;
	}
}
